﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace EzDesk.DevHelper.HtmlToAspx
{
    public class HtmlConvertor: EzTfsConverter
    {
        private string _sourcefileName;
        private string _fileContent;
        private string _outputFileName;
        private string _outputFolderName;

        private string[] templateContentNameArray = {
            "pageTitle", "pageStyles", "pageScripts", "pageHead", "pageContent", "pageShortcut", "pageFoot"
    };


        public HtmlConvertor(string sourceFileName, string outputFolderName = null)
        {
            this._sourcefileName = sourceFileName;
            this._outputFolderName = outputFolderName;

            _outputFileName = getDestFileName(_sourcefileName);
        }


        private string getDestFileName(string sourceFileName)
        {
            string newFileName = Path.ChangeExtension(sourceFileName, "aspx");

            string directoryName = Path.GetDirectoryName(newFileName);;
            if (!string.IsNullOrEmpty(_outputFolderName))
            {
                directoryName = _outputFolderName;
            }
            _outputFolderName = directoryName;

            string simpleFileName = Path.GetFileName(newFileName);

            int indexOfUnderLine = simpleFileName.IndexOf('_');
            string categoryName = simpleFileName.Substring(0, indexOfUnderLine);
            string aspxFileName = simpleFileName
                .Substring(indexOfUnderLine + 1, simpleFileName.Length - indexOfUnderLine - 1);
            //首字母大写
            aspxFileName = aspxFileName[0].ToString().ToUpper() + aspxFileName.Substring(1, aspxFileName.Length - 1);
            string fullDirectoryName = directoryName + "\\" + categoryName;
            if (!Directory.Exists(fullDirectoryName))
            {
                Directory.CreateDirectory(fullDirectoryName);
            }
            string outputFileName = Path.Combine(fullDirectoryName, aspxFileName);
            return outputFileName;
        }

        public void Convert()
        {
            using (var sr = new StreamReader(_sourcefileName))
            {
                _fileContent = sr.ReadToEnd();
            }

            //读取目标模板
            string targetStr = "";
            using (var sr = new StreamReader(TemplateName))
            {
                targetStr = sr.ReadToEnd();
            }

            // 替换模板小节
            targetStr = templateBlockReplace(targetStr);

            // 替换js和css的路径
            targetStr = jsAndCssPathReplace(targetStr);

            // 清除mock数据
            // todo: Mock数据格式不统一，暂时先不启用这个功能
            //targetStr = removeMockData(targetStr);

            // 替换 <!-- <% %>  -->的注释
            targetStr = removeServerSideCodeComment(targetStr);

            using (var fs = new FileStream(_outputFileName, FileMode.Create))
            {
                using (var sw = new StreamWriter(fs, Encoding.UTF8))
                {
                    sw.Write(targetStr);
                    sw.Flush();
                }
            }
        }

        private string removeServerSideCodeComment(string targetStr)
        {
            string pattern1 = @"<!--.*?(?=<%)";
            string pattern2 = @"(?<=%>).*?-->";

            targetStr = regexReplaceString(targetStr, pattern1, string.Empty);
            targetStr = regexReplaceString(targetStr, pattern2, string.Empty);

            return targetStr;
        }

        private string removeMockData(string targetStr)
        {
            string pattern1 = @"if \(ezmock.IS_MOCKED\) {[\s\S]*?(?=var realEzAccessor)";
            string pattern2 = @"(?<=EzAccessor = realEzAccessor;)[\s\S]*?}";
            
            targetStr = regexReplaceString(targetStr, pattern1, string.Empty);
            targetStr = regexReplaceString(targetStr, pattern2, string.Empty);
            
            return targetStr;
        }

        private string jsAndCssPathReplace(string targetStr)
        {
            targetStr = regexReplaceString(targetStr, "src=\"Content", "src=\"../../Content");
            targetStr = regexReplaceString(targetStr, "href=\"Content", "href=\"../../Content");

            targetStr = regexReplaceString(targetStr, "src=\"Scripts", "src=\"../../Scripts");
            targetStr = regexReplaceString(targetStr, "href=\"Scripts", "href=\"../../Scripts");

            return targetStr;
        }

        private string regexReplaceString(string targetStr, string pattern, string replacement)
        {
            return Regex.Replace(targetStr, pattern, replacement);
        }

        private string templateBlockReplace(string targetStr)
        {
            string blockStartStrTpl = "<!-- InstanceBeginEditable name=\"{0}\" -->";
            string blockEndStr = @"<!-- InstanceEndEditable -->";
            foreach (var item in templateContentNameArray)
            {
                // 每个地方替换
                string blockStartStr = string.Format(blockStartStrTpl, item);
                string replaceSign = "{" + item + "}";
                string regexPatternTpl = @"(?<={0})[\s\S]*?(?={1})";
                
                // 形如 (?<=<!-- InstanceBeginEditable name="pageTitle" -->)[\s\S]*?(?=<!-- InstanceEndEditable -->) 的正则匹配
                Regex regex = new Regex(string.Format(regexPatternTpl, blockStartStr, blockEndStr));
                string replaceContent = regex.Match(_fileContent).Value;

                // 取消服务器代码的注释
                string pattern = @"//.*?(?=<%=)";
                regex = new Regex(pattern);
                var matchCollection = regex.Matches(replaceContent);
                int offset = 0;
                foreach (Match match in matchCollection)
                {
                    replaceContent = replaceContent.Remove(match.Index - offset, 2);
                    offset += 2;
                }

                targetStr = targetStr.Replace(replaceSign, replaceContent);
            }
            return targetStr;
        }


        public string TemplateName = "template.tpl";

        public override List<string> SourceFiles()
        {
            return new List<string>()
            {
                _sourcefileName
            };
        }

        public override string GetDestFile(string sourceFile)
        {
            return getDestFileName(sourceFile);
        }
    }
}
